home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / asm / adisv1_3.lha / src / disasm_code.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-20  |  6.0 KB  |  260 lines

  1. /*
  2.  * Change history
  3.  * $Log:    disasm_code.c,v $
  4.  * Revision 3.0  93/09/24  17:53:52  Martin_Apel
  5.  * New feature: Added extra 68040 FPU opcodes
  6.  * 
  7.  * Revision 2.1  93/07/18  22:55:46  Martin_Apel
  8.  * *** empty log message ***
  9.  * 
  10.  * Revision 2.0  93/07/01  11:53:49  Martin_Apel
  11.  * *** empty log message ***
  12.  * 
  13.  * Revision 1.15  93/07/01  11:39:11  Martin_Apel
  14.  * Minor mod.: Removed dependance on ctype.h
  15.  * 
  16.  * Revision 1.14  93/06/06  13:46:15  Martin_Apel
  17.  * Minor mod.: Replaced first_pass and read_symbols by pass1, pass2, pass3
  18.  * 
  19.  * Revision 1.13  93/06/03  20:25:45  Martin_Apel
  20.  * Minor mod.: Additional linefeed generation for end instructions has been
  21.  *             moved to format_line
  22.  * 
  23.  */
  24.  
  25. #include <exec/types.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include "defs.h"
  29.  
  30. static char rcsid [] = "$Id: disasm_code.c,v 3.0 93/09/24 17:53:52 Martin_Apel Exp $";
  31.  
  32. short disasm_instr ()
  33.  
  34. /**********************************************************************/
  35. /*    Returns number of words disassembled                            */
  36. /**********************************************************************/
  37.  
  38. {
  39. register struct opcode_entry *op;
  40. short size;
  41.  
  42. opcode [0] = src [0] = dest [0] = 0;
  43. size = 0;
  44.  
  45. for (op = &(opcode_table [(code [0]) >> 6]);
  46.      size == 0; 
  47.      op = &(opcode_table [op->chain]))
  48.   {
  49.   /* Test for validity of ea_mode */
  50.   if (op->modes & (1 << MODE_NUM (*code)))
  51.     {
  52.     if ((MODE_NUM (*code) == 7) && !(op->submodes & (1 << REG_NUM (*code))))
  53.       continue;
  54.  
  55.     if (pass3 && op->mnemonic != 0)
  56.       {
  57.       strcpy (opcode, op->mnemonic);
  58.       }
  59.     size = (*op->handler) (op);
  60.     }
  61.   }
  62.  
  63. return (size);
  64. }
  65.  
  66. /**************************************************************************/
  67.  
  68. PRIVATE void disasm_code_2nd (USHORT *seg, ULONG seg_size)
  69.  
  70. {
  71. short instr_size;
  72. UBYTE *b_ptr;
  73. int i;
  74. int data_size;
  75. BOOL write_far_directives = FALSE;
  76. static ULONG last_address_printed = 0L;
  77. BOOL currently_far;                /* Is true when all current instructions
  78.                                       are meant as far */
  79.  
  80. if (try_small)
  81.   {
  82.   currently_far = FALSE;
  83.   /*
  84.   put ("                    NEAR           CODE\n\n");
  85.   */
  86.   put ("                    NEAR\n\n");
  87.   }
  88. else
  89.   {
  90.   currently_far = TRUE;
  91.   /*
  92.   put ("                    FAR            CODE\n\n");
  93.   */
  94.   put ("                    FAR\n\n");
  95.   }
  96.  
  97.  
  98. b_ptr = (UBYTE*)seg;
  99. for (current_address = first_address; current_address < last_address;)
  100.   {
  101.   if (verbose && (current_address - last_address_printed > 0x200))
  102.     {
  103.     printf (">%5lx\r", current_address);
  104.     fflush (stdout);
  105.     last_address_printed = current_address;
  106.     }
  107.   if (IS_CODE (current_address))
  108.     {    
  109. #ifdef DEBUG
  110.     if (current_address & 1)
  111.       fprintf (stderr, "Code starting at odd address: %lx\n", current_address);
  112. #endif
  113.     end_instr = FALSE;
  114.     code = (USHORT*)b_ptr;
  115.     instr_size = disasm_instr ();
  116. #ifdef DEBUG
  117.     if (detected_illegal)
  118.       fprintf (stderr, "Detected illegal opcode during second pass at %lx\n", 
  119.                current_address);
  120. #endif
  121.     if (try_small)
  122.       {
  123.       /* The instruction word itself can't be relocated */
  124.       for (i = 2; i < instr_size * 2; i += 2)
  125.         {
  126.         if (IS_RELOCATED (current_address + i))
  127.           write_far_directives = TRUE;
  128.         }
  129.       }
  130.  
  131.     format_line (FALSE, TRUE);
  132.     if (!currently_far && write_far_directives)
  133.       {
  134.       /*
  135.       put ("\n                    FAR            CODE\n");
  136.       */
  137.       put ("\n                    FAR\n");
  138.       currently_far = TRUE;
  139.       }
  140.     else if (currently_far && !write_far_directives && try_small)
  141.       {
  142.       /*
  143.       put ("                    NEAR           CODE\n\n");
  144.       */
  145.       put ("                    NEAR\n\n");
  146.       currently_far = FALSE;
  147.       }
  148.  
  149.     put (instruction);
  150.     write_far_directives = FALSE;
  151.  
  152.     b_ptr += 2 * instr_size;
  153.     current_address += 2 * instr_size;
  154.     }
  155.   else 
  156.     {
  157.     i = current_address;    
  158.     while (!IS_CODE (i) && i < last_address)
  159.       i++;
  160.     data_size = i - current_address;
  161.     disasm_data (b_ptr, data_size);
  162.     b_ptr += data_size;
  163.     }
  164.   }
  165.  
  166. put ("\n");
  167. }
  168.  
  169. /**************************************************************************/
  170.  
  171. PRIVATE void quick_and_dirty (USHORT *seg, ULONG seg_size)
  172.  
  173. {
  174. short instr_size;
  175. int i;
  176. BOOL write_far_directives = FALSE;
  177. ULONG last_address_printed;
  178. BOOL currently_far;                /* Is true when all current instructions
  179.                                       are meant as far */
  180. if (try_small)
  181.   {
  182.   currently_far = FALSE;
  183.   put ("                    NEAR\n\n");
  184.   }
  185. else
  186.   {
  187.   currently_far = TRUE;
  188.   put ("                    FAR\n\n");
  189.   }
  190.  
  191.  
  192. last_address_printed = first_address;
  193. code = seg;
  194. for (current_address = first_address; current_address < last_address;)
  195.   {
  196.   if (verbose && (current_address - last_address_printed > 0x200))
  197.     {
  198.     printf (">%5lx\r", current_address);
  199.     fflush (stdout);
  200.     last_address_printed = current_address;
  201.     }
  202.  
  203.   detected_illegal = FALSE;
  204.   end_instr = FALSE;
  205.   instr_size = disasm_instr ();
  206.   if (detected_illegal || current_address + 2 * instr_size > last_address)
  207.     {
  208.     strcpy (opcode, "DC.W");
  209.     format_d (src, *code, FALSE);
  210.     dest [0] = 0;
  211.     instr_size = 1;
  212.     }
  213.  
  214.   if (try_small)
  215.     {
  216.     /* The instruction word itself can't be relocated */
  217.     for (i = 2; i < instr_size * 2; i += 2)
  218.       {
  219.       if (IS_RELOCATED (current_address + i))
  220.         write_far_directives = TRUE;
  221.       }
  222.     }
  223.  
  224.   format_line (TRUE, TRUE);
  225.   if (!currently_far && write_far_directives)
  226.     {
  227.     put ("\n                    FAR\n");
  228.     currently_far = TRUE;
  229.     }
  230.   else if (currently_far && !write_far_directives && try_small)
  231.     {
  232.     put ("                    NEAR\n\n");
  233.     currently_far = FALSE;
  234.     }
  235.  
  236.   put (instruction);
  237.   write_far_directives = FALSE;
  238.  
  239.   code += instr_size;
  240.   current_address += 2 * instr_size;
  241.   }
  242.  
  243. put ("\n");
  244. }
  245.  
  246. /**************************************************************************/
  247.  
  248. void disasm_code (USHORT *seg, ULONG seg_size)
  249.  
  250. {
  251. if (pass2)
  252.   {
  253.   disasm_code_1st (seg, seg_size);
  254.   }
  255. else if (disasm_quick)
  256.   quick_and_dirty (seg, seg_size);
  257. else
  258.   disasm_code_2nd (seg, seg_size);
  259. }
  260.